package com.plian.system.service.pf.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.cache.UserCache;
import com.plian.system.common.status.CheckStatus;
import com.plian.system.config.exception.MyRuntimeException;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.entity.im.ProjectInfo;
import com.plian.system.entity.pf.*;
import com.plian.system.entity.sys.ApprovalMessage;
import com.plian.system.enumeratea.BusinessIndicatorsStatus;
import com.plian.system.mapper.pf.BaseBusinessIndicatorsMapper;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.im.IProjectInfoService;
import com.plian.system.service.pf.*;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.message.IApprovalMessageService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.pf.BaseBusinessIndicatorsVO;
import com.plian.system.vo.yth.YthResult;
import com.plian.system.wrapper.pf.BaseBusinessIndicatorsWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.GZW_TYPE;
import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * @Author: Take-off
 * @Description: TODO 经营业绩考核指标主表-变更-服务类
 * @Date: 2023/1/3 2:39 PM
 * @Version: 1.0
 **/
@Slf4j
@Service
@AllArgsConstructor
public class BaseIndicatorsChangeServiceImpl extends BaseServiceImpl<BaseBusinessIndicatorsMapper, BaseBusinessIndicators> implements IBaseIndicatorsChangeService, BaseFlowService {

    private FormWorkflowService formWorkflowService;

    private IFormCodeService formCodeService;

    private IBusinessIndicatorsService businessIndicatorsService;

    private ITaskIndicatorsService taskIndicatorsService;

    private IMajorProjectService majorProjectService;

    private IMainBusinessService mainBusinessService;

    private BaseBusinessIndicatorsWrapper baseBusinessIndicatorsWrapper;

    private IOrgService orgService;

    private IAppraisalIndexService appraisalIndexService;

    private IProjectInfoService projectInfoService;

    private IApprovalMessageService approvalMessageService;

    @Override
    public boolean saveOrUpdate(BaseBusinessIndicators baseBusinessIndicators) {
        baseBusinessIndicators.setModuleType(0);
        if (!Optional.ofNullable(baseBusinessIndicators.getStatus()).isPresent()) {
            baseBusinessIndicators.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (baseBusinessIndicators.getStatus().equals(FormStatusConstant.REJECT)) {
            baseBusinessIndicators.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (!Optional.ofNullable(baseBusinessIndicators.getId()).isPresent()) {
            baseBusinessIndicators.setCode(formCodeService.getCode(FormTypeConstant.PF_BASE_BUSINESS_INDICATORS_CHANGE_OLD));
            baseBusinessIndicators.setFormType(String.valueOf(FormTypeConstant.PF_BASE_BUSINESS_INDICATORS_CHANGE_OLD));
            baseBusinessIndicators.setVersion(baseBusinessIndicators.getVersion() + 1);
            baseBusinessIndicators.setIsLatest(1);
            baseBusinessIndicators.setIndicatorStatus(BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
            updateLangStatus(baseBusinessIndicators.getInitialId(), BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
        }

        return super.saveOrUpdate(baseBusinessIndicators);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BaseBusinessIndicators baseBusinessIndicators = getById(id);
            if (baseBusinessIndicators == null) {
                return false;
            } else if (baseBusinessIndicators.getStatus() != null &&
                    (baseBusinessIndicators.getStatus() != FormStatusConstant.STASH && baseBusinessIndicators.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            updateLangStatus(baseBusinessIndicators.getInitialId(), BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
            update(Wrappers.<BaseBusinessIndicators>lambdaUpdate()
                    .eq(BaseBusinessIndicators::getInitialId, baseBusinessIndicators.getInitialId())
                    .eq(BaseBusinessIndicators::getVersion, baseBusinessIndicators.getVersion() - 1)
                    .set(BaseBusinessIndicators::getIsLatest, 2));
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }

        boolean result = super.deleteLogic(ids);
        if (result){
            businessIndicatorsService.deleteByParentId(ids);
            taskIndicatorsService.deleteByParentId(ids);
            majorProjectService.deleteByParentId(ids);
            mainBusinessService.deleteByParentId(ids);
        }
        return result;
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW, null);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        BaseBusinessIndicators indicators = getById(id);
        updateLangStatus(indicators.getInitialId(), BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
        updateIsLatest(indicators.getInitialId());
        indicators.setApprovedUser(TokenUtil.getTokenUserId());
        Date now = DateUtil.now();
        indicators.setApprovedTime(now);
        indicators.setIsLatest(2);
        indicators.setIndicatorStatus(BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
        updateById(indicators);

        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH,"审批通过");
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState, comment);
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BaseBusinessIndicators> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseBusinessIndicators::getModuleType,0);
        queryWrapper.in(BaseBusinessIndicators::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BaseBusinessIndicators> baseBusinessIndicators = list(queryWrapper);
        List<BaseBusinessIndicatorsVO> baseBusinessIndicatorsVOS = baseBusinessIndicatorsWrapper.entityToVO(baseBusinessIndicators);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(baseBusinessIndicatorsVOS)){
                for (BaseBusinessIndicatorsVO vo : baseBusinessIndicatorsVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getFillingUnitName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getFillingUnitId());
                    pd.put("formType", FormTypeConstant.PF_BASE_BUSINESS_INDICATORS_CHANGE_OLD);
                    pd.put("orgName", vo.getFillingUnitName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.PF_BASE_BUSINESS_INDICATORS_CHANGE_OLD);
    }

    @Override
    public void goBackToStash(String formId) {
        Long id = Long.valueOf(formId);
        BaseBusinessIndicators indicators = getById(id);
        if (indicators.getStatus() == FormStatusConstant.FINISH){
            if (indicators.getIsLatest() != null && indicators.getIsLatest() != 2){
                throw new MyRuntimeException(new ObjResult("该指标信息不是最新  不可回退！"));
            }
            LambdaUpdateWrapper<BaseBusinessIndicators> updateWrapper = new LambdaUpdateWrapper<>();
            update(updateWrapper.eq(BaseBusinessIndicators::getId, id)
                    .set(BaseBusinessIndicators::getApprovedUser, null).set(BaseBusinessIndicators::getApprovedTime, null));
            updateLangStatus(indicators.getInitialId(), BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
            updateIsLatest(indicators.getInitialId());
            List<BaseBusinessIndicators> baseBusinessIndicators = list(new LambdaUpdateWrapper<BaseBusinessIndicators>().eq(BaseBusinessIndicators::getInitialId, id)
                    .eq(BaseBusinessIndicators::getModuleType,0)
                    .orderByDesc(BaseBusinessIndicators::getVersion));
            if (CollectionUtil.isNotEmpty(baseBusinessIndicators) && baseBusinessIndicators.size() > 1){
                BaseBusinessIndicators businessIndicators = baseBusinessIndicators.get(1);
                businessIndicators.setIsLatest(2);
                updateById(businessIndicators);
            }
        }

        handleStatus(Long.valueOf(formId), UNREVIEWED, null);
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus,String comment) {
        try {
            BaseBusinessIndicators baseBusinessIndicators = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                baseBusinessIndicators.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                baseBusinessIndicators.setApprovedTime(now);
            }
            if (StringUtil.isNotBlank(baseBusinessIndicators.getDataSource()) &&
                    StringUtil.isNotBlank(baseBusinessIndicators.getDataSourceId())){
                if (updateStatus == FormStatusConstant.FINISH || updateStatus == FormStatusConstant.REJECT){
                    ApprovalMessage approvalMessage = new ApprovalMessage();
                    approvalMessage.setDataSourceId(baseBusinessIndicators.getDataSourceId());
                    approvalMessage.setOpinion(comment);
                    approvalMessage.setIsApprove(updateStatus == FormStatusConstant.FINISH ? 2 : 1);
                    approvalMessage.setIsSend(1);
                    approvalMessage.setDataSourceType(GZW_TYPE);

                    if (baseBusinessIndicators.getDataSource().equals(YthConstant.DATA_NINGBO)) {
                        approvalMessage.setDataSourceType(YthConstant.DATA_NINGBO);
                        approvalMessage.setFilingUserName(UserCache.userIdToName(TokenUtil.getTokenUserId()));
                        approvalMessage.setFormType(FormTypeConstant.PF_BASE_BUSINESS_INDICATORS_CHANGE_OLD);
                        approvalMessage.setFilingCode(baseBusinessIndicators.getCode());
                    }
                    approvalMessageService.save(approvalMessage);
                }
            }
            baseBusinessIndicators.setStatus(updateStatus);
            updateById(baseBusinessIndicators);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(BaseBusinessIndicators baseBusinessIndicators) {
        baseBusinessIndicators.setModuleType(0);
        boolean result = saveOrUpdate(baseBusinessIndicators);
        if (result){
            List<BusinessIndicators> businessIndicatorsList = baseBusinessIndicators.getBusinessIndicators();
            if (CollectionUtil.isNotEmpty(businessIndicatorsList)){
                for (BusinessIndicators businessIndicators : businessIndicatorsList){
                    if (businessIndicators.getId() != null &&
                            Optional.ofNullable(businessIndicators.getIsDeleted()).isPresent() && businessIndicators.getIsDeleted().intValue() == 1) {
                        businessIndicatorsService.removeById(businessIndicators.getId());
                    }else {
                        businessIndicators.setBaseBusinessIndicatorsId(baseBusinessIndicators.getId());
                        businessIndicatorsService.saveOrUpdate(businessIndicators);
                    }
                }
            }
            List<TaskIndicators> taskIndicators = baseBusinessIndicators.getTaskIndicators();
            if (CollectionUtil.isNotEmpty(taskIndicators)){
                for (TaskIndicators taskIndicator : taskIndicators){
                    if (taskIndicator.getId() != null &&
                            Optional.ofNullable(taskIndicator.getIsDeleted()).isPresent() && taskIndicator.getIsDeleted().intValue() == 1) {
                        taskIndicatorsService.removeById(taskIndicator.getId());
                    }else {
                        taskIndicator.setBaseBusinessIndicatorsId(baseBusinessIndicators.getId());
                        taskIndicatorsService.saveOrUpdate(taskIndicator);
                    }
                }
            }

            List<MajorProject> majorProjects = baseBusinessIndicators.getMajorProjects();
            if (CollectionUtil.isNotEmpty(majorProjects)){
                for (MajorProject majorProject : majorProjects){
                    if (majorProject.getId() != null &&
                            Optional.ofNullable(majorProject.getIsDeleted()).isPresent() && majorProject.getIsDeleted().intValue() == 1) {
                        majorProjectService.removeById(majorProject.getId());
                    }else {
                        majorProject.setBaseBusinessIndicatorsId(baseBusinessIndicators.getId());
                        majorProjectService.saveOrUpdate(majorProject);
                    }
                }
            }

            List<MainBusiness> mainBusinesses = baseBusinessIndicators.getMainBusinesses();
            if (CollectionUtil.isNotEmpty(mainBusinesses)){
                for (MainBusiness mainBusiness : mainBusinesses){
                    if (mainBusiness.getId() != null &&
                            Optional.ofNullable(mainBusiness.getIsDeleted()).isPresent() && mainBusiness.getIsDeleted().intValue() == 1) {
                        mainBusinessService.removeById(mainBusiness.getId());
                    }else {
                        mainBusiness.setBaseBusinessIndicatorsId(baseBusinessIndicators.getId());
                        mainBusinessService.saveOrUpdate(mainBusiness);
                    }
                }
            }

        }
        return result;
    }

    private void updateLangStatus(Long initialId, int landStatus){
        update(new LambdaUpdateWrapper<BaseBusinessIndicators>().eq(BaseBusinessIndicators::getInitialId, initialId).eq(BaseBusinessIndicators::getModuleType,0).set(BaseBusinessIndicators::getIndicatorStatus, landStatus));
    }

    private void updateIsLatest(Long initialId){
        update(new LambdaUpdateWrapper<BaseBusinessIndicators>().eq(BaseBusinessIndicators::getInitialId, initialId)
                .eq(BaseBusinessIndicators::getIsLatest, 2).eq(BaseBusinessIndicators::getModuleType,0).set(BaseBusinessIndicators::getIsLatest, 1));
    }

    @Override
    public String saveChangeBusiness(String data) {
        YthResult ythResult = new YthResult();
        //成功的id集合
        List<String> successIds = new ArrayList<>();
        //失败的id集合
        List<String> failIds = new ArrayList<>();
        //失败的原因
        List<String> failReasons = new ArrayList<>();
        //将json字符串转换成list
        List<BaseBusinessIndicators> dataList = JSON.parseArray(data, BaseBusinessIndicators.class);
        if (CollectionUtil.isNotEmpty(dataList)) {
            Map<String, String> orgSourceMap = orgService.getSourceId();
            List<ProjectInfo> projectInfos = projectInfoService.list(new LambdaQueryWrapper<ProjectInfo>().eq(ProjectInfo::getDataSource, 3));
            //code
            List<AppraisalIndex> indexList = appraisalIndexService.listByTableCode("001");
            //根据datasourceIds 查询出所有的数据
            List<BaseBusinessIndicators> list = list(new LambdaQueryWrapper<BaseBusinessIndicators>().in(BaseBusinessIndicators::getDataSourceId, dataList.stream().map(BaseBusinessIndicators::getDataSourceId).toArray())
                    .eq(BaseBusinessIndicators::getModuleType,0).eq(BaseBusinessIndicators::getStatus, UNREVIEWED));

            if (CollectionUtil.isNotEmpty(list)) {
                //删除子集
                List<Long> ids = list.stream().map(BaseBusinessIndicators::getId).collect(Collectors.toList());
                businessIndicatorsService.deleteByParentId(ids);
                taskIndicatorsService.deleteByParentId(ids);
                majorProjectService.deleteByParentId(ids);
                mainBusinessService.deleteByParentId(ids);
            }
            for (BaseBusinessIndicators entity:dataList){
                String transfer = transfer(entity, orgSourceMap, indexList, projectInfos);
                if (StringUtil.isNotBlank(transfer)){
                    //id重复略过
                    if (CollectionUtil.isNotEmpty(list)){
                        List<String> olIds = list.stream().map(BaseBusinessIndicators::getDataSourceId).collect(Collectors.toList());
                        String dataSourceId = entity.getDataSourceId();
                        //判断数据库中是否有数据
                        if (olIds.contains(dataSourceId)){
                            for (BaseBusinessIndicators oldEntity:list){
                                if (dataSourceId.equals(oldEntity.getDataSourceId())){
                                    //判断status是否为0，如果是0，就更新，不是0，就不更新
                                    if (CheckStatus.checkCode(oldEntity.getStatus())){
                                        successIds.add(dataSourceId);
                                        entity.setId(oldEntity.getId());
                                        entity.setDataSource(YthConstant.DATA_NINGBO);
                                        submit(entity);
                                        list.remove(oldEntity);
                                        break;
                                    }else {
                                        failIds.add(dataSourceId);
                                        failReasons.add("dataSourceId:"+dataSourceId+"数据已提交且已经在流程中，无法更新");
                                        break;
                                    }
                                }
                            }
                        }else {
                            //如果数据库中没有数据，就新增
                            entity.setDataSource(YthConstant.DATA_NINGBO);
                            submit(entity);
                            successIds.add(entity.getDataSourceId());
                        }
                    }else {
                        //如果数据库中没有数据，就新增
                        entity.setDataSource(YthConstant.DATA_NINGBO);
                        submit(entity);
                        successIds.add(entity.getDataSourceId());
                    }
                }else {
                    failReasons.add(transfer);
                }

            }
        }else {
            failReasons.add("数据为空");
        }
        ythResult.setSuccessIds(successIds);
        ythResult.setFailIds(failIds);
        ythResult.setFailReason(StringUtils.join(failReasons, ";"));
        //ythResult转换成json字符串
        return JSON.toJSONString(ythResult);
    }

    private String transfer(BaseBusinessIndicators entity, Map<String, String> orgSourceMap,List<AppraisalIndex> indexList
            ,List<ProjectInfo> projectInfos){
        StringBuilder msg = new StringBuilder();
        //获取老的版本
        Optional.ofNullable(entity.getDataInitialId()).ifPresent(initId ->{
            Optional.ofNullable(getOne(Wrappers.<BaseBusinessIndicators>lambdaQuery().eq(BaseBusinessIndicators::getDataSource, YthConstant.DATA_NINGBO)
                    .eq(BaseBusinessIndicators::getModuleType,0).eq(BaseBusinessIndicators::getDataSourceId, initId))).ifPresent(initOne ->{
                //获取之前的变更记录
                List<BaseBusinessIndicators> changeList = list(Wrappers.<BaseBusinessIndicators>lambdaQuery().eq(BaseBusinessIndicators::getInitialId, initOne.getId())
                        .eq(BaseBusinessIndicators::getModuleType,0));
                if (CollectionUtil.isNotEmpty(changeList)){
                    changeList.stream().max(Comparator.comparing(BaseBusinessIndicators::getFillingTime)).ifPresent(lasted ->{
                        if (Optional.ofNullable(lasted.getStatus()).isPresent() && lasted.getStatus()  == FormStatusConstant.FINISH){
                            //已经审核通过
                            entity.setLastVersionId(lasted.getId());
                            entity.setInitialId(lasted.getInitialId());
                            entity.setVersion(lasted.getVersion());
                        }else {
                            msg.append("上一条变更数据还在流程中").append(",");
                        }
                    });
                }else {
                    //还没有变更过
                    if (Optional.ofNullable(initOne.getStatus()).isPresent() && initOne.getStatus()  == FormStatusConstant.FINISH){
                        //已经审核通过
                        entity.setLastVersionId(initOne.getId());
                        entity.setInitialId(initOne.getId());
                        entity.setVersion(initOne.getVersion());
                    }else {
                        msg.append("上一条变更数据还在流程中").append(",");
                    }
                }
            });
        });

        Optional.ofNullable(entity.getFillingUnitId()).ifPresent(m ->
                {
                    String orgId = orgSourceMap.get(m);
                    if (StringUtil.isNotBlank(orgId)){
                        entity.setFillingUnitId(orgId);
                        entity.setCreateCompanyId(orgId);
                    }
                }
        );
        //转换code
        List<BusinessIndicators> businessIndicators = entity.getBusinessIndicators();
        if (CollectionUtil.isNotEmpty(businessIndicators)){
            businessIndicators.forEach( bus ->{
                if (Optional.ofNullable(bus.getIndicatorsCode()).isPresent()){
                    indexList.stream().filter(m ->bus.getIndicatorsCode().equals(m.getCompleteCode())).findFirst().ifPresent(code ->{
                        bus.setIndicatorsCategoryId(code.getId());
                        bus.setIndicatorsCategoryName(code.getName());
                    });
                }else {
                    //其他
                    indexList.stream().filter(m ->m.getType() == 1 && m.getFlag() == 2).findFirst().ifPresent(code ->{
                        bus.setIndicatorsCategoryId(code.getId());
                    });
                }
            });
        }
        List<TaskIndicators> taskIndicators = entity.getTaskIndicators();
        if (CollectionUtil.isNotEmpty(taskIndicators)){
            taskIndicators.forEach( task ->{
                if (Optional.ofNullable(task.getIndicatorsCode()).isPresent()){
                    if ("ZDRW".equals(task.getIndicatorsCode())){
                        indexList.stream().filter(m ->m.getType() == 2 && m.getSort() == 1).findFirst().ifPresent(code ->{
                            task.setIndicatorsCategoryId(code.getId());
                        });
                    }else if ("LSRW".equals(task.getIndicatorsCode())){
                        indexList.stream().filter(m ->m.getType() == 2 && m.getSort() == 2).findFirst().ifPresent(code ->{
                            task.setIndicatorsCategoryId(code.getId());
                        });
                    }
                }
            });
        }

        List<MajorProject> majorProjects = entity.getMajorProjects();
        if (CollectionUtil.isNotEmpty(majorProjects)){
            majorProjects.forEach(project ->{
                if (Optional.ofNullable(project.getDataProjectId()).isPresent()){
                    projectInfos.stream().filter(m -> project.getDataProjectId().equals(m.getDataSourceId())).findFirst().ifPresent(proInfo ->{
                        project.setProjectId(proInfo.getId());
                        project.setProjectName(proInfo.getProjectName());
                    });
                }
            });
        }
        return msg.toString().substring(0,msg.length()-1);
    }

}
